package com.client.controller.auth;

import com.client.Initialize;
import com.client.entity.B_client;
import com.client.mapper.MessageDao;
import com.client.mapper.PassAuthorDao;
import com.client.service.*;
import com.client.sm9.gm.sm9.G1KeyPair;
import com.client.sm9.gm.sm9.ResultKeyExchange;
import com.client.sm9.gm.sm9.SM9Utils;
import com.client.utils.MessageUtils;
import com.client.utils.UDPUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.stereotype.Component;

import java.sql.Timestamp;
import java.util.Date;
import java.util.Map;

@Component
@Slf4j
public class Exchange {
    @Autowired
    Sm9Service userService;
    @Autowired
    Certification certification;
    @Autowired
    ExchangeService exchangeService;
    @Autowired
    KeyService keyService;
    @Autowired
    UDPUtil udp;
    @Autowired
    PassAuthorDao passAuthorDao;
    @Autowired
    MessageService messageService;
    @Autowired
    MigrationService migrationService;
    @Autowired
    MessageDao messageDao;

    @Value("${udp.receive}")
    private Integer port;


    @ServiceActivator(inputChannel = "exchange1")
    public void udpMessageHandle6(Map<String, Object> map, @Headers Map<String, Object> headers) {
        String id = (String) map.get("id");
        B_client client = messageService.getClient(id);
        if (client != null && client.getFlag() == -2 && client.getExchang_flag() == 0) {
            log.info("收到[" + id + "]的密钥交换请求1");
            //更新对象状态
            client.setGoal_R((byte[]) map.get("R"));
            client.setSponsor(false);
            updateTime((Date) map.get("time"),client,map);

            //处理密钥交换1
            if (!Initialize.HPS) {
                G1KeyPair g1KeyPair = exchangeService.Exchange1(client);

                ResultKeyExchange resultKeyExchange = exchangeService.Exchange2(client.getGoal_id(), client.isSponsor(), client.getGoal_R(), g1KeyPair);

                //修改状态
                client.setMy_S(resultKeyExchange.getSA2());
                client.setK(resultKeyExchange.getSK());
                client.setMyKeyPair(g1KeyPair);
                client.setResultKeyExchange(resultKeyExchange);

                byte[] body_b = exchangeService.exchange2(client);
                //发送udp包
                send(client, body_b,true);
                //修改状态
                client.setExchang_flag(2);
            } else {
                migrationService.Exchange1(client);
            }

        } else if (client == null) {
            log.info("收到[" + id + "]的密钥交换请求1，但认证列表不存在该对象");
        } else if (client.getFlag() != -2) {
            log.info("收到[" + id + "]的密钥交换请求1，但并未完成认证");
        } else if (client.getExchang_flag() > 0) {
            log.info("收到[" + id + "]的密钥交换请求1，但该请求已经处理过");
        }
    }

    @ServiceActivator(inputChannel = "exchange2")
    public void udpMessageHandle7(Map<String, Object> map, @Headers Map<String, Object> headers) {
        String id = (String) map.get("id");
        B_client client = messageService.getClient(id);
        if (client != null && client.getFlag() == -2 && client.getExchang_flag() == 1) {
            log.info("收到[" + id + "]的密钥交换请求2");
            //更新对象状态
            client.setGoal_R((byte[]) map.get("R"));
            client.setGoal_S((byte[]) map.get("S"));
            updateTime((Date) map.get("time"),client,map);

            //处理密钥交换2
            if (!Initialize.HPS) {
                ResultKeyExchange resultKeyExchange = exchangeService.Exchange2(id, client.isSponsor(), client.getGoal_R(), client.getMyKeyPair());
                client.setMy_S(resultKeyExchange.getSB1());
                client.setK(resultKeyExchange.getSK());
                client.setResultKeyExchange(resultKeyExchange);
                //现在已知SB\S2\K与SA,将Rb与SB发给对方

                if (!SM9Utils.byteEqual(client.getGoal_S(), client.getMy_S())) {
                    client.setExchang_flag(-1);
                    log.info("[" + id + "]的密钥交换请求失败：goal_S与my_S不相同！");
                    return;
                } else {
                    log.info("[" + id + "]的密钥交换请求成功！密钥为：" + SM9Utils.toHexPureString(client.getK()));
                }
                byte[] body_b = exchangeService.exchange3(client);
                //发送udp包
                send(client, body_b,true);
                //修改状态
                client.setExchang_flag(3);
            } else {
                migrationService.Exchange2(client.getGoal_id(),client.getUid() ,client.isSponsor(),
                        16, client.getMyKeyPair(), client.getGoal_R());
            }


        } else if (client == null) {
            log.info("收到[" + id + "]的密钥交换请求2，但认证列表不存在该对象");
        } else if (client.getFlag() != -2) {
            log.info("收到[" + id + "]的密钥交换请求2，但并未完成认证");
        } else if (client.getExchang_flag() > 1) {
            log.info("收到[" + id + "]的密钥交换请求2，但该请求已经处理过");
        } else if (client.getExchang_flag() < 1) {
            log.info("收到[" + id + "]的密钥交换请求2，但尚未进行到这一步");
        }
    }

    @ServiceActivator(inputChannel = "exchange3")
    public void udpMessageHandle8(Map<String, Object> map, @Headers Map<String, Object> headers) {
        String id = (String) map.get("id");
        B_client client = messageService.getClient(id);
        if (client != null && client.getFlag() == -2 && client.getExchang_flag() == 2) {
            log.info("收到[" + id + "]的密钥交换请求3");
            //更新对象状态
            client.setGoal_S((byte[]) map.get("S"));
            updateTime((Date) map.get("time"),client,map);

            //现在已知SB\S2\K与SA,将Rb与SB发给对方

            if (!SM9Utils.byteEqual(client.getGoal_S(), client.getMy_S())) {
                client.setExchang_flag(-1);
                log.info("[" + id + "]的密钥交换请求失败：goal_S与my_S不相同！");
                return;
            } else {
                log.info("[" + id + "]的密钥交换请求成功！密钥为：" + SM9Utils.toHexPureString(client.getK()));
            }
            byte[] body_b = exchangeService.exchange4(client);

            //发送udp包
            send(client, body_b,false);
            //修改状态
            client.setExchang_flag(-2);

            //保存到数据库
            if (passAuthorDao.queryByName(id) == null)
                passAuthorDao.add(id, client.getK(), client.getGoal_ip(), client.getGoal_port());
            else
                passAuthorDao.updateK(client.getK(), id);

//            messageService.deleteClient(id);不立即删除，使其他方法可以查询认证状态，在30s未更新后会自动删除

        } else if (client == null) {
            log.info("收到[" + id + "]的密钥交换请求3，但认证列表不存在该对象");
        } else if (client.getFlag() != -2) {
            log.info("收到[" + id + "]的密钥交换请求3，但并未完成认证");
        } else if (client.getExchang_flag() > 2) {
            log.info("收到[" + id + "]的密钥交换请求3，但该请求已经处理过");
        } else if (client.getExchang_flag() < 2) {
            log.info("收到[" + id + "]的密钥交换请求3，但尚未进行到这一步");
        }
    }

    @ServiceActivator(inputChannel = "exchange4")
    public void udpMessageHandle9(Map<String, Object> map, @Headers Map<String, Object> headers) {
        String id = (String) map.get("id");
        B_client client = messageService.getClient(id);
        if (client != null && client.getFlag() == -2 && client.getExchang_flag() == 3) {
            log.info("收到[" + id + "]的密钥交换请求4,双方都已确认密钥交换成功");
            //修改状态
            client.setExchang_flag(-2);
            updateTime((Date) map.get("time"),client,map);
            //保存到数据库
            if (passAuthorDao.queryByName(id) == null)
                passAuthorDao.add(id, client.getK(), client.getGoal_ip(), client.getGoal_port());
            else
                passAuthorDao.updateK(client.getK(), id);

//            messageService.deleteClient(id); 不立即删除，使其他方法可以查询认证状态，在30s未更新后会自动删除

        } else if (client == null) {
            log.info("收到[" + id + "]的密钥交换请求4，但认证列表不存在该对象");
        } else if (client.getFlag() != -2) {
            log.info("收到[" + id + "]的密钥交换请求4，但并未完成认证");
        } else if (client.getExchang_flag() < 3) {
            log.info("收到[" + id + "]的密钥交换请求4，但尚未进行到这一步");
        }
    }

    public void send(B_client client, byte[] msg, boolean isNeedReply) {
        if (isNeedReply)
            MessageService.addMessage(client.getUid().toString(), client.getGoal_ip(), client.getGoal_port(), msg,
                    MessageUtils.getNowTime(), 8, 30);
        udp.send(client.getGoal_ip(), client.getGoal_port(), msg);
    }

    public void updateTime(Date time,B_client client,Map<String, Object> map){
        MessageService.deleteMessage(client.getUid().toString());
        client.setTime(time);
        messageDao.add(client.getGoal_id(),keyService.getId(),client.getGoal_ip(),client.getGoal_port(),client.getUid().toString(),map.get("uuid").toString(),
                0,map.get("type").toString(),new Timestamp(MessageUtils.getNowTime().getTime()));
    }
}
